﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Isis.Extensions;
using Isis.Helpers.Impl;
using Isis.Helpers.Interfaces;
using Isis.Interfaces;
using Isis.Model;
using Isis.Views;

namespace Isis.Controllers
{
    public class ServerController : IControlPanelController
    {
        private readonly string _basePath;
        private readonly IServerInfoHelper _serverInfoHelper;
         
        public ServerController(string basePath) : this(basePath, new ServerInfoHelper())
        {
        }

        public ServerController(string basePath, IServerInfoHelper serverInfoHelper)
        {
            _basePath = basePath;
            _serverInfoHelper = serverInfoHelper;
        }

        public ControllerTab Tab
        {
            get { return new ControllerTab("Server"); }
        }

        public string Action { get; set; }

        public string Parameter { get; set; }

        public IEnumerable<string> SubTabs
        {
            get { return new[] {"System", "Processes"}; }
        }

        public void Render(TextWriter writer)
        {
            var pageLayoutWriter = new PageLayoutWriter(Tab.Title, Action, new ControllerRepository(), _basePath);
            pageLayoutWriter.RenderPage(writer, RenderContent);
        }

        private void RenderContent(TextWriter writer)
        {
            switch(Action)
            {
                case "system":
                default:
                    RenderSystemProperties(writer);
                    break;
                case "processes":
                    RenderProcesses(writer);
                    break;
            }
        }

        private void RenderSystemProperties(TextWriter writer)
        {
            //writer.Write("<p class=\"note\">Server Info</p>");
            writer.Write("<p>Machine Name: {0}</p>", Environment.MachineName);
            writer.Write("<p>Operating System: {0}</p>", Environment.OSVersion.VersionString);
            writer.Write("<p>Architecture: {0}</p>", _serverInfoHelper.GetCpuArchitecture());
            writer.Write("<p>.NET CLR Version: {0}</p>", Environment.Version);
            writer.Write("<p>Processors: {0}</p>", Environment.ProcessorCount);
            writer.Write("<p>Uptime: {0}</p>", TimeSpan.FromMilliseconds(Environment.TickCount));
            writer.Write("<p>User Domain: {0}</p>", FuncExtensions.SafeGetValue(() => Environment.UserDomainName));
            writer.Write("<p>User: {0}</p>", FuncExtensions.SafeGetValue(() => Environment.UserName));
            writer.Write("<p>Folder: {0}</p>", FuncExtensions.SafeGetValue(() => Environment.CurrentDirectory));
            writer.Write("<p>CPU Usage: {0:P}</p>", FuncExtensions.SafeGetValue(_serverInfoHelper.GetCpuUsage));
            writer.Write("<p>Available RAM: {0:#,#} Mb</p>", FuncExtensions.SafeGetValue(_serverInfoHelper.GetAvailableRam));
            writer.Write("<p>Total Machine RAM: {0:#,#} Mb</p>", FuncExtensions.SafeGetValue(_serverInfoHelper.GetTotalRam));
        }

        private void RenderProcesses(TextWriter writer)
        {
            var tableHelper = new TableRenderingHelper();

            var sb = new StringBuilder();

            try
            {
                var processIds = _serverInfoHelper.GetProcessIds();

                if (processIds.Any())
                {
                    sb.Append(tableHelper.RenderTableHeader("Processes"));
                    sb.Append(tableHelper.RenderHeaderRow(new[] { "Name", "Id", "Memory Usage", "Threads" }));

                    foreach (int id in processIds)
                    {
                        sb.AppendLine(
                            tableHelper.RenderRow(new[]
                        {
                            _serverInfoHelper.GetProcessNameById(id), 
                            id.ToString(), 
                            _serverInfoHelper.GetProcessPrivateMemorySize64ById(id).ToString("#,0"),
                            _serverInfoHelper.GetProcessThreadCount(id).ToString(),
                        }));
                    }

                    sb.Append("</table>");
                }
            }
            catch (Exception)
            {
                sb.Append("<p>Processes unavailable</p>");
            }

            writer.Write(sb.ToString());
        }
    }
}